//
//  JSONCodableUtil.swift
//  ObjcCodable
//
//  Created by chenbo on 2025/2/10.
//

import Foundation

// JSONDecodable工具类
struct JSONDecodableUtil<T: Decodable> {
    
    /// 构造方法不对外暴露
    private init() {}
    
    /// 从Data创建实例模型
    static func instance(from data: Data?) -> T? {
        guard let data else {
            return nil
        }
        let decoder = JSONDecoder()
        guard let res = try? decoder.decode(T.self, from: data) else {
            return nil
        }
        return res
    }
    
    /// 从字典创建实例模型
    static func decode(jsonObject object: Any?) -> T? {
        guard let object else {
            return nil
        }
        guard let data = try? JSONSerialization.data(withJSONObject: object, options: .prettyPrinted) else {
            return nil
        }
        guard let res = self.instance(from: data) else {
            return nil
        }
        return res
    }
    
    /// 从JSON字符串生成实例模型
    static func decode(jsonString: String?) -> T? {
        guard let data = jsonString?.data(using: .utf8) else {
            return nil
        }
        guard let res = self.instance(from: data) else {
            return nil
        }
        return res
    }
}

/// JSONEncodable工具类
struct JSONEncodableUtil {
    
    /// 构造方法不对外暴露
    private init() {}
    
    static func jsonData(_ encodableObj: Encodable) -> Data? {
        let encoder = JSONEncoder()
        guard let data = try? encoder.encode(encodableObj) else {
            return nil
        }
        return data
    }
    
    /// 把模型转换成JSON字符串
    static func jsonString(_ encodableObj: Encodable) -> String? {
        guard let data = self.jsonData(encodableObj) else {
            return nil
        }
        guard let jsonStr = String(data: data, encoding: .utf8) else {
            return nil
        }
        return jsonStr
    }
    
    /// 把模型转换成JSON对象
    static func jsonObject(_ encodableObj: Encodable) -> Any? {
        guard let data = self.jsonData(encodableObj) else {
            return nil
        }
        guard let obj = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)  else {
            return nil
        }
        return obj
    }
}
